home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2005 June (DVD) / DPPRO0605DVD.iso / Install / program files / Borland / BDS / 3.0 / Demos / Delphi.Net / VCL / CustomDraw / CustomDrawTreeView.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2004-10-22  |  11.4 KB  |  403 lines

  1. unit CustomDrawTreeView;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   ComCtrls, ExtDlgs, StdCtrls, ExtCtrls, ColorGrd, ImgList, Menus, Types;
  8.  
  9. type
  10.   TCustomDrawForm = class(TForm)
  11.     TV: TTreeView;
  12.     ImageList: TImageList;
  13.     MainMenu1: TMainMenu;
  14.     Drawing1: TMenuItem;
  15.     Font1: TMenuItem;
  16.     Background1: TMenuItem;
  17.     Color1: TMenuItem;
  18.     Bitmap1: TMenuItem;
  19.     DefaultDrawing1: TMenuItem;
  20.     OnCustomDraw1: TMenuItem;
  21.     OnCustomDrawItem1: TMenuItem;
  22.     BrushStyle1: TMenuItem;
  23.     Solid1: TMenuItem;
  24.     Clear1: TMenuItem;
  25.     Horizontal1: TMenuItem;
  26.     Vertical1: TMenuItem;
  27.     FDiagonal1: TMenuItem;
  28.     BDiagonal1: TMenuItem;
  29.     Cross1: TMenuItem;
  30.     DiagCross1: TMenuItem;
  31.     File1: TMenuItem;
  32.     Exit1: TMenuItem;
  33.     N2: TMenuItem;
  34.     TVFontDialog: TFontDialog;
  35.     Tile1: TMenuItem;
  36.     Stretch1: TMenuItem;
  37.     None1: TMenuItem;
  38.     Selection1: TMenuItem;
  39.     SelectedFontDialog: TFontDialog;
  40.     BkgColorDialog: TColorDialog;
  41.     SelBkgColorDialog: TColorDialog;
  42.     SelectionBackground1: TMenuItem;
  43.     ButtonColor1: TMenuItem;
  44.     ButtonSize1: TMenuItem;
  45.     ButtonColorDialog: TColorDialog;
  46.     Image1: TImage;
  47.     TreeView1: TMenuItem;
  48.     Color2: TMenuItem;
  49.     TVColorDialog: TColorDialog;
  50.     CustomDraw1: TMenuItem;
  51.     Font2: TMenuItem;
  52.     procedure FormCreate(Sender: TObject);
  53.     procedure TVCustomDraw(Sender: TCustomTreeView; const ARect: TRect;
  54.       var DefaultDraw: Boolean);
  55.     procedure TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
  56.       State: TCustomDrawState; var DefaultDraw: Boolean);
  57.     procedure TVGetImageIndex(Sender: TObject; Node: TTreeNode);
  58.     procedure TVGetSelectedIndex(Sender: TObject; Node: TTreeNode);
  59.     procedure Exit1Click(Sender: TObject);
  60.     procedure Selection1Click(Sender: TObject);
  61.     procedure Color1Click(Sender: TObject);
  62.     procedure SelectionBackground1Click(Sender: TObject);
  63.     procedure Solid1Click(Sender: TObject);
  64.     procedure None1Click(Sender: TObject);
  65.     procedure OnCustomDraw1Click(Sender: TObject);
  66.     procedure OnCustomDrawItem1Click(Sender: TObject);
  67.     procedure TVExpanded(Sender: TObject; Node: TTreeNode);
  68.     procedure ButtonColor1Click(Sender: TObject);
  69.     procedure ButtonSize1Click(Sender: TObject);
  70.     procedure Drawing1Click(Sender: TObject);
  71.     procedure Color2Click(Sender: TObject);
  72.     procedure CustomDraw1Click(Sender: TObject);
  73.     procedure Font2Click(Sender: TObject);
  74.   private
  75.     FButtonSize: Integer;
  76.     FDefaultDraw,
  77.     FDefaultDrawItem: Boolean;
  78.     FBackgroundColor: TColor;
  79.     FBrushStyle: TBrushStyle;
  80.     procedure DrawButton(ARect: TRect; Node: TTreeNode);
  81.     procedure DrawImage(NodeRect: TRect; ImageIndex: Integer);
  82.     procedure SetCustomDraw(Value: Boolean);
  83.     { Private declarations }
  84.   public
  85.     { Public declarations }
  86.   end;
  87.  
  88. var
  89.   CustomDrawForm: TCustomDrawForm;
  90.  
  91. implementation
  92.  
  93. {$R *.dfm}
  94.  
  95. procedure TCustomDrawForm.FormCreate(Sender: TObject);
  96. begin
  97.   FBackgroundColor := clWindow;
  98.   FDefaultDraw := True;
  99.   FDefaultDrawItem := True;
  100.   FBrushStyle := bsSolid;
  101.   FButtonSize := 5;
  102.   BkgColorDialog.Color := clWindow;
  103.   SelBkgColorDialog.Color := clHighlight;
  104.   TVFontDialog.Font.Assign(TV.Font);
  105.   SelectedFontDialog.Font.Assign(TV.Font);
  106.   SelectedFontDialog.Font.Color := clHighlightText;
  107.   SelBkgColorDialog.Color := clHighlight;
  108.   TVColorDialog.Color := TV.Color;
  109. end;
  110.  
  111. procedure TCustomDrawForm.TVCustomDraw(Sender: TCustomTreeView; const ARect: TRect;
  112.   var DefaultDraw: Boolean);
  113. begin
  114. //This event should be used to draw any background colors or images.
  115. //ARect represents the entire client area of the TreeView.
  116. //Use the TreeView's canvas to do the drawing.
  117. //Note that drawing a background bitmap is not really supported by CustomDraw,
  118. //so scrolling can get messy. Best to subclass the TreeView and handle scrolling
  119. //messages.
  120.   with TV.Canvas do
  121.   begin
  122.     if None1 <> nil then
  123.     begin
  124.       if None1.Checked then //no picture
  125.       begin
  126.         Brush.Color := BkgColorDialog.Color;
  127.         Brush.Style := FBrushStyle;
  128.         FillRect(ARect);
  129.       end else
  130.         if Tile1.Checked then //tile bitmap
  131.         begin
  132.           Brush.Bitmap := Image1.Picture.Bitmap;
  133.             FillRect(ARect);
  134.           end else //Stretch across the canvas.
  135.               StretchDraw(ARect, Image1.Picture.Bitmap);
  136.     end;
  137.   end;
  138.   DefaultDraw := FDefaultDraw;
  139.   //setting DefaultDraw to false here prevents all calls to OnCustomDrawItem.
  140. end;
  141.  
  142. procedure TCustomDrawForm.DrawButton(ARect: TRect; Node: TTreeNode);
  143. var
  144.   cx, cy: Integer;
  145. begin
  146.   cx := ARect.Left + TV.Indent div 2;
  147.   cy := ARect.Top + (ARect.Bottom - ARect.Top) div 2;
  148.   with TV.Canvas do
  149.   begin
  150.     Pen.Color := ButtonColorDialog.Color;
  151.     //draw horizontal line.
  152.     if Node.HasChildren then
  153.     begin
  154.       PenPos := Point(cx+FButtonSize, cy);
  155.       LineTo(ARect.Left + TV.Indent + FButtonSize, cy);
  156.     end else
  157.     begin
  158.       PenPos := Point(cx, cy);
  159.       LineTo(ARect.Left + TV.Indent + FButtonSize, cy);
  160.     end;
  161.  
  162.     //draw half vertical line, top portion.
  163.     PenPos := Point(cx, cy);
  164.     LineTo(cx, ARect.Top-1);
  165.  
  166.     if ((Node.GetNextVisible <> nil) and (Node.GetNextVisible.Level = Node.Level))
  167.     or (Node.GetNextSibling <> nil) then
  168.     //draw bottom portion of half vertical line.
  169.     begin
  170.       PenPos := Point(cx, cy);
  171.       LineTo(cx, ARect.Bottom+1);
  172.     end;  
  173.  
  174.     if Node.HasChildren then
  175.     begin
  176.       //Let's try a circular button instead
  177.       Ellipse(cx-FButtonSize, cy-FButtonSize, cx+FButtonSize, cy+FButtonSize);
  178.  
  179.       //draw the horizontal indicator.
  180.       PenPos := Point(cx-FButtonSize+2, cy);
  181.       LineTo(cx+FButtonSize-2, cy);
  182.       //draw the vertical indicator if the node is collapsed
  183.       if not Node.Expanded then
  184.       begin
  185.         PenPos := Point(cx, cy-FButtonSize+2);
  186.         LineTo(cx, cy+FButtonSize-2);
  187.       end;
  188.     end;
  189.         //now connect vertical lines of higher level nodes.
  190.     Node := Node.Parent;
  191.     while Node <> nil do
  192.     begin
  193.       cx := cx - TV.Indent;
  194.       if Node.GetNextSibling <> nil then
  195.       begin
  196.         PenPos := Point(cx, ARect.Top);
  197.         LineTo(cx, ARect.Bottom);
  198.       end;
  199.       Node := Node.Parent;
  200.     end;
  201.   end;
  202. end;
  203.  
  204. procedure TCustomDrawForm.DrawImage(NodeRect: TRect; ImageIndex: Integer);
  205. var
  206.   cy: Integer;
  207. begin
  208.   cy := NodeRect.Top + (NodeRect.Bottom - NodeRect.Top) div 2;
  209.   //center image in NodeRect.
  210.   ImageList.Draw(TV.Canvas, NodeRect.Left, cy - TV.Images.Height div 2,
  211.                  ImageIndex, True);
  212. end;
  213.  
  214. procedure TCustomDrawForm.TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
  215.   State: TCustomDrawState; var DefaultDraw: Boolean);
  216. var
  217.   NodeRect: TRect;
  218. begin
  219.   with TV.Canvas do
  220.   begin
  221.     //If DefaultDraw it is true, any of the node's font properties can be
  222.     //changed. Note also that when DefaultDraw = True, Windows draws the
  223.     //buttons and ignores our font background colors, using instead the
  224.     //TreeView's Color property.
  225.     if cdsSelected in State then
  226.     begin
  227.       Font.Assign(SelectedFontDialog.Font);
  228.       Brush.Color := SelBkgColorDialog.Color;
  229.     end;
  230.  
  231.     DefaultDraw := FDefaultDrawItem;
  232.     //DefaultDraw = False means you have to handle all the item drawing yourself,
  233.     //including the buttons, lines, images, and text.
  234.     if not DefaultDraw then
  235.     begin
  236.       //draw the selection rect.
  237.       if cdsSelected in State then
  238.       begin
  239.         NodeRect := Node.DisplayRect(True);
  240.         FillRect(NodeRect);
  241.       end;
  242.       NodeRect := Node.DisplayRect(False);
  243.  
  244.       if None1.Checked then
  245.       //no bitmap, so paint in the background color.
  246.       begin
  247.         Brush.Color := BkgColorDialog.Color;
  248.         Brush.Style := FBrushStyle;
  249.         FillRect(NodeRect)
  250.       end
  251.       else
  252.         //don't paint over the background bitmap.
  253.         Brush.Style := bsClear;
  254.  
  255.       NodeRect.Left := NodeRect.Left + (Node.Level * TV.Indent);
  256.       //NodeRect.Left now represents the left-most portion of the expand button
  257.       DrawButton(NodeRect, Node);
  258.  
  259.       NodeRect.Left := NodeRect.Left + TV.Indent + FButtonSize;
  260.       //NodeRect.Left is now the leftmost portion of the image.
  261.       DrawImage(NodeRect, Node.ImageIndex);
  262.  
  263.       NodeRect.Left := NodeRect.Left + ImageList.Width;
  264.       //Now we are finally in a position to draw the text.
  265.  
  266.       TextOut(NodeRect.Left, NodeRect.Top, Node.Text);
  267.     end;
  268.   end;
  269. end;
  270.  
  271. procedure TCustomDrawForm.TVGetImageIndex(Sender: TObject; Node: TTreeNode);
  272. begin
  273.   if Node.HasChildren then
  274.     if Node.Expanded then
  275.       Node.ImageIndex := 3
  276.     else
  277.       Node.ImageIndex := 0
  278.   else
  279.     Node.ImageIndex := 1;
  280. end;
  281.  
  282. procedure TCustomDrawForm.TVGetSelectedIndex(Sender: TObject; Node: TTreeNode);
  283. begin
  284.   Node.SelectedIndex := Node.ImageIndex;
  285. end;
  286.  
  287. procedure TCustomDrawForm.Exit1Click(Sender: TObject);
  288. begin
  289.   Close;
  290. end;
  291.  
  292. procedure TCustomDrawForm.Selection1Click(Sender: TObject);
  293. begin
  294.   if SelectedFontDialog.Execute then
  295.     TV.Repaint;
  296. end;
  297.  
  298. procedure TCustomDrawForm.Color1Click(Sender: TObject);
  299. begin
  300.   if BkgColorDialog.Execute then
  301.     TV.Repaint;
  302. end;
  303.  
  304. procedure TCustomDrawForm.SelectionBackground1Click(Sender: TObject);
  305. begin
  306.   if SelBkgColorDialog.Execute then
  307.     TV.Repaint;
  308. end;
  309.  
  310. procedure TCustomDrawForm.Solid1Click(Sender: TObject);
  311. begin
  312.   with Sender as TMenuItem do
  313.   begin
  314.     FBrushStyle := TBrushStyle(Tag);
  315.     Checked := True;
  316.   end;
  317.   TV.Repaint;
  318. end;
  319.  
  320. procedure TCustomDrawForm.None1Click(Sender: TObject);
  321. begin
  322.   (Sender as TMenuItem).Checked := True;
  323.   TV.Repaint;
  324. end;
  325.  
  326. procedure TCustomDrawForm.OnCustomDraw1Click(Sender: TObject);
  327. begin
  328.   FDefaultDraw := not FDefaultDraw;
  329.   OnCustomDraw1.Checked := FDefaultDraw;
  330.   TV.Repaint;
  331. end;
  332.  
  333. procedure TCustomDrawForm.OnCustomDrawItem1Click(Sender: TObject);
  334. begin
  335.   FDefaultDrawItem := not FDefaultDrawItem;
  336.   OnCustomDrawItem1.Checked := FDefaultDrawItem;
  337.   TV.Repaint;
  338. end;
  339.  
  340. procedure TCustomDrawForm.TVExpanded(Sender: TObject; Node: TTreeNode);
  341. begin
  342.   TV.Repaint;
  343. end;
  344.  
  345. procedure TCustomDrawForm.ButtonColor1Click(Sender: TObject);
  346. begin
  347.   if ButtonColorDialog.Execute then TV.Repaint;
  348. end;
  349.  
  350. procedure TCustomDrawForm.ButtonSize1Click(Sender: TObject);
  351. var
  352.   S: string;
  353. begin
  354.   S := IntToStr(FButtonSize);
  355.   if InputQuery('Change button size', 'Enter new size', S) then
  356.     FButtonSize := StrToInt(S);
  357.   TV.Repaint;  
  358. end;
  359.  
  360. procedure TCustomDrawForm.Drawing1Click(Sender: TObject);
  361. begin
  362.   ButtonColor1.Enabled := not OnCustomDrawItem1.Checked;
  363.   ButtonSize1.Enabled := ButtonColor1.Enabled;
  364. end;
  365.  
  366. procedure TCustomDrawForm.Color2Click(Sender: TObject);
  367. begin
  368.   if TVColorDialog.Execute then
  369.   begin
  370.     TV.Color := TVColorDialog.Color;
  371.     TV.Repaint;
  372.   end;
  373. end;
  374.  
  375. procedure TCustomDrawForm.SetCustomDraw(Value: Boolean);
  376. begin
  377.   if not Value then
  378.   begin
  379.     TV.OnCustomDraw := nil;
  380.     TV.OnCustomDrawItem := nil;
  381.   end else
  382.   begin
  383.     TV.OnCustomDraw := Self.TVCustomDraw;
  384.     TV.OnCustomDrawItem := Self.TVCustomDrawItem;
  385.   end;
  386.   Drawing1.Enabled := Value;
  387.   TV.Repaint;
  388. end;
  389.  
  390. procedure TCustomDrawForm.CustomDraw1Click(Sender: TObject);
  391. begin
  392.   CustomDraw1.Checked := not CustomDraw1.Checked;
  393.   SetCustomDraw(CustomDraw1.Checked);
  394. end;
  395.  
  396. procedure TCustomDrawForm.Font2Click(Sender: TObject);
  397. begin
  398.   if TVFontDialog.Execute then
  399.     TV.Font.Assign(TVFontDialog.Font);
  400. end;
  401.  
  402. end.
  403.